package pso.data;

import java.beans.PropertyChangeSupport;

import pso.PSOAlgorithm;
import pso.PSOAlgorithmFactory;
import evolution.problem.OptimizationProblem;

public abstract class SlavePSO {
	protected double cognitiveFactor = 2.05;
	protected double socialFactor = 2.05;
	protected int swarmSize = 40;

	public SlavePSO() {
	}

	public SlavePSO(SlavePSO other) {
		cognitiveFactor = other.cognitiveFactor;
		socialFactor = other.socialFactor;
		swarmSize = other.swarmSize;
	}

	protected PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
			this);

	public double getCognitiveFactor() {
		return cognitiveFactor;
	}

	public void setCognitiveFactor(double c1) {
		this.cognitiveFactor = c1;
	}

	public double getSocialFactor() {
		return socialFactor;
	}

	public void setSocialFactor(double c2) {
		this.socialFactor = c2;
	}

	public int getSwarmSize() {
		return swarmSize;
	}

	public void setSwarmSize(int swarmSize) {
		this.swarmSize = swarmSize;
	}

	public abstract PSOAlgorithm build(OptimizationProblem problem,
			int iterations);

	public static class SlaveClassicPSO extends SlavePSO {

		public SlaveClassicPSO() {
		}

		public SlaveClassicPSO(SlavePSO other) {
			super(other);
		}

		@Override
		public PSOAlgorithm build(OptimizationProblem problem, int iterations) {
			return PSOAlgorithmFactory.createClassicPSO(problem, iterations,
					swarmSize, cognitiveFactor, socialFactor);
		}

		@Override
		public String toString() {
			return "SlaveClassicPSO [cognitiveFactor=" + cognitiveFactor
					+ ", socialFactor=" + socialFactor + ", swarmSize="
					+ swarmSize + "]";
		}
	}

	public static class ConstantInertiaPSO extends SlavePSO {

		private double inertiaWeight = 0.7;

		public ConstantInertiaPSO() {
		}

		public ConstantInertiaPSO(SlavePSO other) {
			super(other);
		}

		@Override
		public PSOAlgorithm build(OptimizationProblem problem, int iterations) {
			return PSOAlgorithmFactory.createConstantInertiaWeightPSO(problem,
					iterations, swarmSize, cognitiveFactor, socialFactor,
					inertiaWeight);
		}

		public double getInertiaWeight() {
			return inertiaWeight;
		}

		public void setInertiaWeight(double inertiaWeight) {
			this.inertiaWeight = inertiaWeight;
		}

		@Override
		public String toString() {
			return "ConstantInertiaPSO [inertiaWeight=" + inertiaWeight
					+ ", cognitiveFactor=" + cognitiveFactor
					+ ", socialFactor=" + socialFactor + ", swarmSize="
					+ swarmSize + "]";
		}
	}

	public static class RandomInertiaPSO extends SlavePSO {

		public RandomInertiaPSO() {
		}

		public RandomInertiaPSO(SlavePSO other) {
			super(other);
		}

		@Override
		public PSOAlgorithm build(OptimizationProblem problem, int iterations) {
			return PSOAlgorithmFactory.createRandomInertiaWeightPSO(problem,
					iterations, swarmSize, cognitiveFactor, socialFactor);
		}

		@Override
		public String toString() {
			return "RandomInertiaPSO [cognitiveFactor=" + cognitiveFactor
					+ ", socialFactor=" + socialFactor + ", swarmSize="
					+ swarmSize + "]";
		}
	}

	public static class DecreasingInertiaPSO extends SlavePSO {

		private double beginInertiaWeight = 1.2;
		private double endInertiaWeight = 0.4;

		public DecreasingInertiaPSO() {
		}

		public DecreasingInertiaPSO(SlavePSO other) {
			super(other);
		}

		@Override
		public PSOAlgorithm build(OptimizationProblem problem, int iterations) {
			return PSOAlgorithmFactory.createDecreasingInertiaWeightPSO(
					problem, iterations, swarmSize, cognitiveFactor,
					socialFactor, beginInertiaWeight, endInertiaWeight);
		}

		public double getBeginInertiaWeight() {
			return beginInertiaWeight;
		}

		public void setBeginInertiaWeight(double beginInertiaWeight) {
			this.beginInertiaWeight = beginInertiaWeight;
		}

		public double getEndInertiaWeight() {
			return endInertiaWeight;
		}

		public void setEndInertiaWeight(double endInertiaWeight) {
			this.endInertiaWeight = endInertiaWeight;
		}

		@Override
		public String toString() {
			return "DecreasingInertiaPSO [beginInertiaWeight="
					+ beginInertiaWeight + ", endInertiaWeight="
					+ endInertiaWeight + ", cognitiveFactor=" + cognitiveFactor
					+ ", socialFactor=" + socialFactor + ", swarmSize="
					+ swarmSize + "]";
		}
	}

	public static class ConstrictedPSO extends SlavePSO {

		public ConstrictedPSO() {
		}

		public ConstrictedPSO(SlavePSO other) {
			super(other);
		}

		@Override
		public PSOAlgorithm build(OptimizationProblem problem, int iterations) {
			return PSOAlgorithmFactory.createConstrictedPSO(problem,
					iterations, swarmSize, cognitiveFactor, socialFactor);
		}

		@Override
		public String toString() {
			return "ConstrictedPSO [cognitiveFactor=" + cognitiveFactor
					+ ", socialFactor=" + socialFactor + ", swarmSize="
					+ swarmSize + "]";
		}
	}

}
